package com.gitee.wsl.coroutines.job

import com.gitee.wsl.coroutines.job.exception.SchedulerException
import com.gitee.wsl.coroutines.job.sheduler.IScheduler
import com.gitee.wsl.coroutines.job.trigger.IOperableTrigger
import com.gitee.wsl.time.calendar.Calendar
import kotlin.time.ExperimentalTime
import kotlin.time.Instant

interface IJobFactory {
    /**
     * Called by the scheduler at the time of the trigger firing, in order to
     * produce a `Job` instance on which to call execute.
     *
     *
     * It should be extremely rare for this method to throw an exception -
     * basically only the the case where there is no way at all to instantiate and
     * prepare the Job for execution. When the exception is thrown, the Scheduler
     * will move all triggers associated with the Job into the
     * `Trigger.STATE_ERROR` state, which will require human
     * intervention (e.g. an application restart after fixing whatever
     * configuration problem led to the issue wih instantiating the Job.
     *
     *
     * @param bundle
     * The TriggerFiredBundle from which the `JobDetail` and
     * other info relating to the trigger firing can be obtained.
     * @param scheduler
     * a handle to the scheduler that is about to execute the job.
     * @throws SchedulerException
     * if there is a problem instantiating the Job.
     * @return the newly instantiated Job
     */
    @Throws(SchedulerException::class)
    fun newJob(bundle: TriggerFiredBundle, scheduler: IScheduler): IJob
}

@OptIn(ExperimentalTime::class)
class TriggerFiredBundle(
    val job: JobDetail,
    val trigger: IOperableTrigger,
    val cal: Calendar,
    val isRecovering: Boolean,
    val fireTime: Instant,
    val scheduledFireTime: Instant,
    val prevFireTime: Instant,
    val nextFireTime: Instant,
)